package com.rpc.provider.handler;

import com.rpc.provider.configer.PublishConfiger;
import com.rpc.common.exception.RPCProcessException;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;

/**
 * rpc处理服务器
 * 先用普通socket实现，后面尝试学习使用Netty
 */
@Service
public class RPCProcessServer {
    private ServerSocket serverSocket;
    private ThreadPoolExecutor executor;
    private volatile boolean isStart = false;
    private PublishConfiger configer;

    private static class SingletonHolder {
        public final static RPCProcessServer rpcServerInstance = new RPCProcessServer();
    }

    public void setConfiger(PublishConfiger configer) {
        this.configer = configer;
    }

    /**
     * 私有构造器
     */
    private RPCProcessServer() {

    }

    public static RPCProcessServer getRPCProcessServerInstance() {
        return SingletonHolder.rpcServerInstance;
    }

    private boolean init() {
        if (configer == null) {
            return false;
        }
        try {
            this.serverSocket = new ServerSocket(configer.getPort());
            BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(512);
            RejectedExecutionHandler policy = new ThreadPoolExecutor.DiscardPolicy();
            //确定线程池大小
            int minPoolSize = configer.getMinPoolSize() > 1 ? configer.getMinPoolSize() : 2;
            int maxPoolSize = configer.getMaxPoolSize() < 20 ? configer.getMaxPoolSize() : 20;
            if (maxPoolSize < minPoolSize) {
                maxPoolSize = minPoolSize;
            }

            this.executor = new ThreadPoolExecutor(minPoolSize, maxPoolSize,
                    0, TimeUnit.SECONDS,
                    queue,
                    policy);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务提供方socket启动异常");
        }
        return true;
    }

    /**
     * 先用悲观锁加锁，防止线程不安全 todo 乐观锁优化性能
     */
    public synchronized void startServer() throws RPCProcessException {
        if (isStart) {    //已经启动过
            return;
        }
        if (!init()) { //初始化,如果失败则抛出异常
            throw new RPCProcessException("服务提供方服务初始化失败");
        }
        isStart = true;   //后面再次注册就不会重复启动了
        //启动一个新线程运行server
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        Timer timer = new Timer();
                        timer.schedule(new TimerTask() {
                                           public void run() {
                                               System.out.println("-------服务器运行中--------");
                                           }
                                       }, 1000, 5000
                        );
                        Socket socket = serverSocket.accept();
                        executor.submit(new RPCProcessor(socket));  //提交到线程池中进行处理
                    }

                } catch (IOException e) {
                    System.out.println("服务提供方监听socket失败");
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
